/**
 * 防抖原理：一定时间内，只有最后一次操作，再过wait毫秒后才执行函数
 *
 * @param {Function} func 要执行的回调函数
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
let timeout = null;

function debounce(func, wait = 500, immediate = false) {
    // 清除定时器
    if (timeout !== null) clearTimeout(timeout);
    // 立即执行，此类情况一般用不到
    if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(function () {
            timeout = null;
        }, wait);
        if (callNow) typeof func === "function" && func();
    } else {
        // 设置定时器，当最后一次操作后，timeout不会再被清除，所以在延时wait毫秒后执行func回调方法
        timeout = setTimeout(function () {
            typeof func === "function" && func();
        }, wait);
    }
}

/**
 * 节流原理：在一定时间内，只能触发一次
 *
 * @param {Function} func 要执行的回调函数
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
let timer, flag;

function throttle(func, wait = 500, immediate = true) {
    if (immediate) {
        if (!flag) {
            flag = true;
            // 如果是立即执行，则在wait毫秒内开始时执行
            typeof func === "function" && func();
            timer = setTimeout(() => {
                flag = false;
            }, wait);
        }
    } else {
        if (!flag) {
            flag = true;
            // 如果是非立即执行，则在wait毫秒内的结束处执行
            timer = setTimeout(() => {
                flag = false;
                typeof func === "function" && func();
            }, wait);
        }
    }
}

// 深度克隆
// 判断arr是否为一个数组，返回一个bool值
function deepClone(obj) {
    function isArray(arr) {
        return Object.prototype.toString.call(arr) === "[object Array]";
    }

    // 对常见的“非”值，直接返回原来值
    if ([null, undefined, NaN, false].includes(obj)) return obj;
    if (typeof obj !== "object" && typeof obj !== "function") {
        //原始类型直接返回
        return obj;
    }
    var o = isArray(obj) ? [] : {};
    for (let i in obj) {
        if (obj.hasOwnProperty(i)) {
            o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
        }
    }
    return o;
}

// 浅克隆
function shallowClone(obj) {
    return JSON.parse(JSON.stringify(obj))
}

module.exports = {
    debounce,
    throttle,
    deepClone,
    shallowClone,
    /**
     * 传入一个对象，对象的属性作为参数键，对象属性的值作为参数值，返回对应FormData
     * @param paramObj
     */
    formData(paramObj) {
        if (!paramObj) {
            paramObj = {};
        }
        let data = new FormData();
        Object.keys(paramObj).forEach((key) => data.append(key, paramObj[key]));
        return data;
    },
    //js显示早上好下午好晚上好
    getTimeState() {
        // 获取当前时间
        let timeNow = new Date();
        // 获取当前小时
        let hours = timeNow.getHours();
        // 设置默认文字
        let text = ``;
        // 判断当前时间段
        if (hours >= 0 && hours <= 10) {
            text = `早上好`;
        } else if (hours > 10 && hours <= 14) {
            text = `中午好`;
        } else if (hours > 14 && hours <= 18) {
            text = `下午好`;
        } else if (hours > 18 && hours <= 24) {
            text = `晚上好`;
        }
        // console.log(`hours >>>>>`, hours);
        // console.log(`text >>>>`, text);
        // 返回当前时间段对应的状态
        return text;
    },
    //判断string、object是否为空
    isEmpty(varvar) {
        if (varvar == undefined || varvar == null || !varvar) {
            return true;
        }
        if (typeof varvar == "string") {
            if (varvar.length == 0) {
                return true;
            } else {
                return false;
            }
        } else if (typeof varvar == "object") {
            for (var key in varvar) {
                return false;
            }
            return true;
        }
    },
    // 切换时间格式 2021-07-24 11:32:01 为7月24日 10:19
    needDate(time) {
        const date = new Date(Date.parse(time.replace(/-/g, "/")));

        var year = date.getFullYear() + "年";
        var month = date.getMonth() + 1 + "月";
        var day = date.getDate() + "日";
        var hh = date.getHours() + ":";
        var mm = date.getMinutes();
        var ss = date.getSeconds();
        mm = mm.toString().length < 2 ? "0" + mm : mm;
        return month + day + " " + hh + mm;
    },
    // 标准时间转多少分钟之前
    //2021-04-16 15:53:07
    putDate(time, type = "state") {
        if (!time) {
            return "--";
        }
        const date = Date.parse(time.replace(/-/g, "/"));
        // 时间字符串转时间戳
        var timestamp = new Date(date).getTime();

        var minute = 1000 * 60;
        var hour = minute * 60;
        var day = hour * 24;
        var month = day * 30;
        var year = day * 365;
        var now = new Date().getTime();
        var diffValue = now - timestamp;
        var result;
        if (diffValue < 0) {
            return;
        }
        var yearC = diffValue / year;
        var monthC = diffValue / month;
        var weekC = diffValue / (7 * day);
        var dayC = diffValue / day;
        var hourC = diffValue / hour;
        var minC = diffValue / minute;
        if (yearC >= 1) {
            result = "" + parseInt(yearC) + "年前";
        } else if (monthC >= 1) {
            result = "" + parseInt(monthC) + "月前";
        } else if (weekC >= 1) {
            result = "" + parseInt(weekC) + "周前";
        } else if (dayC >= 1) {
            result = "" + parseInt(dayC) + "天前";
        } else if (hourC >= 1) {
            result = "" + parseInt(hourC) + "小时前";
        } else if (minC >= 5) {
            result = "" + parseInt(minC) + "分钟前";
        } else {
            switch (type) {
                case "state":
                    result = "刚刚活跃";
                    break;
                case "default":
                    result = "刚刚";
                    break;
                case "file":
                    result = "刚刚上传";
                    break;
            }
        }
        return result;
    },
    // 标准时间转时间挫 //2021-08-12 10:2 to 1627698586
    dateToTimestamp(time) {
        const date = new Date(Date.parse(time.replace(/-/g, "/")));
        return Date.parse(date);
    },
    //获取当前时间 格式：2013-01-01  //00:00:00
    curentTime() {
        var now = new Date();

        var year = now.getFullYear();
        var month = now.getMonth() + 1;
        var day = now.getDate();

        var hh = now.getHours();
        var mm = now.getMinutes();

        var clock = year + "-";

        if (month < 10) clock += "0";

        clock += month + "-";

        if (day < 10) clock += "0";

        clock += day + " ";

        /* if (hh < 10) clock += "0";

        clock += hh + ":";
        if (mm < 10) clock += "0";
        clock += mm; */
        return clock;
    },
    //时间戳转换方法    date:时间戳数字 2013-01-01 00:00:00
    formatDate(date) {
        var date = new Date(date);
        var YY = date.getFullYear() + "-";
        var MM = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
        var DD = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
        var hh = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
        var mm = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
        var ss = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
        return YY + MM + DD + " " + hh + mm + ss;
    },
    // 对象转string
    toStr(obj) {
        return encodeURIComponent(JSON.stringify(obj));
    },
    // string转对象
    toObj(str) {
        return JSON.parse(decodeURIComponent(str));
    },

    //be 赋值给 accept  去除掉accept中没有的值
    copyObj(accept, be) {
        Object.keys(accept).forEach((key) => {
            Object.keys(be).forEach((key2) => {
                if (key == key2) {
                    accept[key] = be[key2];
                }
            });
        });
    },
    /**
     * base64转fileleix1
     * @param dataurl base64 url
     * @param filename 文件名
     * @returns {File}
     */
    base64ToFile(dataurl, filename) {
        var arr = dataurl.split(","),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, { type: mime });
    },
    getUUID() {
        var d = new Date().getTime();
        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }
        var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
        });
        return uuid;
    },
    /**
     *
     * @param arr 扁平化转tree
     * @param childrenKey 孩子id名字
     * @param parentKey 父亲id 名字
     * @returns {*}
     */
    changeArr(arr, childrenKey, parentKey) {
        const Arr = JSON.parse(JSON.stringify(arr));
        //将id做为对象的键名，整个对象做为键值 来生成新的数组
        let treeList = Arr.reduce((prev, cur) => {
            prev[cur[childrenKey]] = cur;
            return prev;
        }, {});

        return Arr.reduce((prev, cur) => {
            let pid = cur[parentKey];
            // pid为0的就找不到父对象，找到当前cur的父对象
            // 对象的浅拷贝，引用关系存在，在后面处理parent的时候也会导致cur的改变，达到递归的效果
            let parent = treeList[pid];
            // console.log(parent,1)
            // 如果父对象存在，就将cur压到父对象的children属性中
            if (parent) {
                // parent和cur存在引用关系
                parent.children ? parent.children.push(cur) : (parent.children = [cur]);
            } else if (pid === 0) {
                // 没有父对象，则此cur为树的根元素
                prev.push(cur);
            }
            return prev;
        }, []);
    },

    /**
 *
 * @param arr 扁平化转tree
 * @param childrenKey 孩子id名字
 * @param parentKey 父亲id 名字
 * @returns {*}
 */
    changeArrNoPid0(arr, childrenKey, parentKey) {
        const Arr = JSON.parse(JSON.stringify(arr));
        //将id做为对象的键名，整个对象做为键值 来生成新的数组
        let treeList = Arr.reduce((prev, cur) => {
            prev[cur[childrenKey]] = cur;
            return prev;
        }, {});

        return Arr.reduce((prev, cur) => {
            let pid = cur[parentKey];
            // pid为0的就找不到父对象，找到当前cur的父对象
            // 对象的浅拷贝，引用关系存在，在后面处理parent的时候也会导致cur的改变，达到递归的效果
            let parent = treeList[pid];
            // 如果父对象存在，就将cur压到父对象的children属性中
            if (parent) {
                // parent和cur存在引用关系
                parent.children ? parent.children.push(cur) : (parent.children = [cur]);
                if (!this.isHasObj(prev, cur.id)) {
                    prev.push(parent);
                }
            }
            return prev;
        }, []);
    },
    // 判断对象数组中是否存在某个对象
    isHasObj(arr, val) {
        var flag = false; // true为有 false为没有
        for (var i = 0; i < arr.length; i++) {
            if (JSON.stringify(arr[i]).indexOf(JSON.stringify(val)) != -1) {
                flag = true;
            }
        }
        return flag;
    }
};
